home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 6 / CU Amiga Magazine's Super CD-ROM 06 (1996)(EMAP Images)(GB)(Track 1 of 4)[!][issue 1997-01].iso / cucd / prog / gnu-c / src / gcc-2.7.0-amiga / cp / expr.c < prev    next >
C/C++ Source or Header  |  1995-06-15  |  10KB  |  369 lines

  1. /* Convert language-specific tree expression to rtl instructions,
  2.    for GNU compiler.
  3.    Copyright (C) 1988, 1992, 1993 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 59 Temple Place - Suite 330,
  20. Boston, MA 02111-1307, USA.  */
  21.  
  22.  
  23. #include "config.h"
  24. #include "rtl.h"
  25. #include "tree.h"
  26. #include "flags.h"
  27. #include "expr.h"
  28. #include "cp-tree.h"
  29.  
  30. #undef NULL
  31. #define NULL 0
  32.  
  33. /* Hook used by expand_expr to expand language-specific tree codes.  */
  34.  
  35. rtx
  36. cplus_expand_expr (exp, target, tmode, modifier)
  37.      tree exp;
  38.      rtx target;
  39.      enum machine_mode tmode;
  40.      enum expand_modifier modifier;
  41. {
  42.   tree type = TREE_TYPE (exp);
  43.   register enum machine_mode mode = TYPE_MODE (type);
  44.   register enum tree_code code = TREE_CODE (exp);
  45.   rtx original_target = target;
  46.   int ignore = target == const0_rtx;
  47.  
  48.   if (ignore)
  49.     target = 0, original_target = 0;
  50.  
  51.   /* No sense saving up arithmetic to be done
  52.      if it's all in the wrong mode to form part of an address.
  53.      And force_operand won't know whether to sign-extend or zero-extend.  */
  54.  
  55.   if (mode != Pmode && modifier == EXPAND_SUM)
  56.     modifier = EXPAND_NORMAL;
  57.  
  58.   switch (code)
  59.     {
  60.     case NEW_EXPR:
  61.       {
  62.     /* Something needs to be initialized, but we didn't know
  63.        where that thing was when building the tree.  For example,
  64.        it could be the return value of a function, or a parameter
  65.        to a function which lays down in the stack, or a temporary
  66.        variable which must be passed by reference.
  67.  
  68.        Cleanups are handled in a language-specific way: they
  69.        might be run by the called function (true in GNU C++
  70.        for parameters with cleanups), or they might be
  71.        run by the caller, after the call (true in GNU C++
  72.        for other cleanup needs).  */
  73.  
  74.     tree func = TREE_OPERAND (exp, 0);
  75.     tree args = TREE_OPERAND (exp, 1);
  76.     tree type = TREE_TYPE (exp), slot;
  77.     tree fn_type = TREE_TYPE (TREE_TYPE (func));
  78.     tree return_type = TREE_TYPE (fn_type);
  79.     tree call_exp;
  80.     rtx call_target, return_target;
  81.     int pcc_struct_return = 0;
  82.  
  83.     /* The expression `init' wants to initialize what
  84.        `target' represents.  SLOT holds the slot for TARGET.  */
  85.     slot = TREE_OPERAND (exp, 2);
  86.  
  87.     if (target == 0)
  88.       {
  89.         /* Should always be called with a target in BLKmode case.  */
  90.         my_friendly_assert (mode != BLKmode, 205);
  91.         my_friendly_assert (DECL_RTL (slot) != 0, 206);
  92.  
  93.         target = gen_reg_rtx (mode);
  94.       }
  95.  
  96.     /* The target the initializer will initialize (CALL_TARGET)
  97.        must now be directed to initialize the target we are
  98.        supposed to initialize (TARGET).  The semantics for
  99.        choosing what CALL_TARGET is is language-specific,
  100.        as is building the call which will perform the
  101.        initialization.  It is left here to show the choices that
  102.        exist for C++.  */
  103.        
  104.     if (TREE_CODE (func) == ADDR_EXPR
  105.         && TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL
  106.         && DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0)))
  107.       {
  108.         type = TYPE_POINTER_TO (type);
  109.         /* Don't clobber a value that might be part of a default
  110.            parameter value.  */
  111.         mark_addressable (slot);
  112.         if (TREE_PERMANENT (args))
  113.           args = tree_cons (0, build1 (ADDR_EXPR, type, slot),
  114.                 TREE_CHAIN (args));
  115.         else
  116.           TREE_VALUE (args) = build1 (ADDR_EXPR, type, slot);
  117.         call_target = 0;
  118.       }
  119.     else if (TREE_CODE (return_type) == REFERENCE_TYPE)
  120.       {
  121.         type = return_type;
  122.         call_target = 0;
  123.       }
  124.     else
  125.       {
  126. #ifdef PCC_STATIC_STRUCT_RETURN
  127.         pcc_struct_return = 1;
  128.         call_target = 0;
  129. #else
  130.         call_target = target;
  131. #endif
  132.       }
  133.     if (call_target)
  134.       {
  135.         preserve_temp_slots (call_target);
  136.  
  137.         /* Make this a valid memory address now.  The code below assumes
  138.            that it can compare rtx and make assumptions based on the
  139.            result.  The assumptions are true only if the address was
  140.            valid to begin with.  */
  141.         call_target = validize_mem (call_target);
  142.       }
  143.  
  144.     preserve_temp_slots (DECL_RTL (slot));
  145.     call_exp = build (CALL_EXPR, type, func, args, 0);
  146.     TREE_SIDE_EFFECTS (call_exp) = 1;
  147.     return_target = expand_call (call_exp, call_target, ignore);
  148.     free_temp_slots ();
  149.     if (call_target == 0)
  150.       {
  151.         if (pcc_struct_return)
  152.           {
  153.         extern int flag_access_control;
  154.         int old_ac = flag_access_control;
  155.  
  156.         tree init = build_decl (VAR_DECL, 0, type);
  157.         TREE_ADDRESSABLE (init) = 1;
  158.         DECL_RTL (init) = return_target;
  159.  
  160.         flag_access_control = 0;
  161.         expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
  162.         flag_access_control = old_ac;
  163.  
  164.         if (TYPE_NEEDS_DESTRUCTOR (type))
  165.           {
  166.             init = build_decl (VAR_DECL, 0,
  167.                        build_reference_type (type));
  168.             DECL_RTL (init) = XEXP (return_target, 0);
  169.  
  170.             init = maybe_build_cleanup (convert_from_reference (init));
  171.             if (init != NULL_TREE)
  172.               expand_expr (init, 0, 0, 0);
  173.           }
  174.         call_target = return_target = DECL_RTL (slot);
  175.           }
  176.         else
  177.           call_target = return_target;
  178.       }
  179.  
  180.     if (call_target != return_target)
  181.       {
  182.         my_friendly_assert (TYPE_HAS_TRIVIAL_INIT_REF (type), 317);
  183.         if (GET_MODE (return_target) == BLKmode)
  184.           emit_block_move (call_target, return_target, expr_size (exp),
  185.                    TYPE_ALIGN (type) / BITS_PER_UNIT);
  186.         else
  187.           emit_move_insn (call_target, return_target);
  188.       }
  189.  
  190.     if (TREE_CODE (return_type) == REFERENCE_TYPE)
  191.       {
  192.         tree init;
  193.  
  194.         if (GET_CODE (call_target) == REG
  195.         && REGNO (call_target) < FIRST_PSEUDO_REGISTER)
  196.           my_friendly_abort (39);
  197.  
  198.         type = TREE_TYPE (exp);
  199.  
  200.         init = build (RTL_EXPR, return_type, 0, call_target);
  201.         /* We got back a reference to the type we want.  Now initialize
  202.            target with that.  */
  203.         expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
  204.       }
  205.  
  206.     if (DECL_RTL (slot) != target)
  207.       emit_move_insn (DECL_RTL (slot), target);
  208.     return DECL_RTL (slot);
  209.       }
  210.  
  211.     case OFFSET_REF:
  212.       {
  213. #if 1
  214.     return expand_expr (default_conversion (resolve_offset_ref (exp)),
  215.                 target, tmode, EXPAND_NORMAL);
  216. #else
  217.     /* This is old crusty code, and does not handle all that the
  218.        resolve_offset_ref function does.  (mrs) */
  219.     tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0);
  220.     tree offset = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
  221.     return expand_expr (build (PLUS_EXPR, TREE_TYPE (exp), base, offset),
  222.                 target, tmode, EXPAND_NORMAL);
  223. #endif
  224.       }
  225.  
  226.     case THUNK_DECL:
  227.       return DECL_RTL (exp);
  228.  
  229.     case THROW_EXPR:
  230.       expand_throw (TREE_OPERAND (exp, 0));
  231.       return NULL;
  232.  
  233.     default:
  234.       break;
  235.     }
  236.   my_friendly_abort (40);
  237.   /* NOTREACHED */
  238.   return NULL;
  239. }
  240.  
  241. void
  242. init_cplus_expand ()
  243. {
  244.   lang_expand_expr = cplus_expand_expr;
  245. }
  246.  
  247. /* If DECL had its rtl moved from where callers expect it
  248.    to be, fix it up.  RESULT is the nominal rtl for the RESULT_DECL,
  249.    which may be a pseudo instead of a hard register.  */
  250.  
  251. void
  252. fixup_result_decl (decl, result)
  253.      tree decl;
  254.      rtx result;
  255. {
  256.   if (REG_P (result))
  257.     {
  258.       if (REGNO (result) >= FIRST_PSEUDO_REGISTER)
  259.     {
  260.       rtx real_decl_result;
  261.  
  262. #ifdef FUNCTION_OUTGOING_VALUE
  263.       real_decl_result
  264.         = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl), current_function_decl);
  265. #else
  266.       real_decl_result
  267.         = FUNCTION_VALUE (TREE_TYPE (decl), current_function_decl);
  268. #endif
  269.       REG_FUNCTION_VALUE_P (real_decl_result) = 1;
  270.       result = real_decl_result;
  271.     }
  272.       store_expr (decl, result, 0);
  273.       emit_insn (gen_rtx (USE, VOIDmode, result));
  274.     }
  275. }
  276.  
  277. /* Return nonzero iff DECL is memory-based.  The DECL_RTL of
  278.    certain const variables might be a CONST_INT, or a REG
  279.    in some cases.  We cannot use `memory_operand' as a test
  280.    here because on most RISC machines, a variable's address
  281.    is not, by itself, a legitimate address.  */
  282.  
  283. int
  284. decl_in_memory_p (decl)
  285.      tree decl;
  286. {
  287.   return DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == MEM;
  288. }
  289.  
  290. /* Expand this initialization inline and see if it's simple enough that
  291.    it can be done at compile-time.  */
  292.  
  293. static tree
  294. extract_aggr_init (decl, init)
  295.      tree decl, init;
  296. {
  297.   return 0;
  298. }
  299.  
  300. static tree
  301. extract_scalar_init (decl, init)
  302.      tree decl, init;
  303. {
  304.   rtx value, insns, insn;
  305.   extern struct obstack temporary_obstack;
  306.   tree t = NULL_TREE;
  307.  
  308.   push_obstacks (&temporary_obstack, &temporary_obstack);
  309.   start_sequence ();
  310.   value = expand_expr (init, NULL_RTX, VOIDmode, 0);
  311.   insns = get_insns ();
  312.   end_sequence ();
  313.   reg_scan (insns, max_reg_num (), 0);
  314.   jump_optimize (insns, 0, 0, 1);
  315.   pop_obstacks ();
  316.  
  317.   for (insn = insns; insn; insn = NEXT_INSN (insn))
  318.     {
  319.       rtx r, to;
  320.  
  321.       if (GET_CODE (insn) == NOTE)
  322.     continue;
  323.       else if (GET_CODE (insn) != INSN)
  324.     return 0;
  325.  
  326.       r = PATTERN (insn);
  327.       if (GET_CODE (r) != SET)
  328.     return 0;
  329.  
  330.       to = XEXP (r, 0);
  331.  
  332.       if (! (to == value ||
  333.          (GET_CODE (to) == SUBREG && XEXP (to, 0) == value)))
  334.     return 0;
  335.  
  336.       r = XEXP (r, 1);
  337.  
  338.       switch (GET_CODE (r))
  339.     {
  340.     case CONST_INT:
  341.       t = build_int_2 (XEXP (r, 0), 0);
  342.       break;
  343.     default:
  344.       return 0;
  345.     }
  346.     }
  347.  
  348.   return t; 
  349. }
  350.  
  351. int
  352. extract_init (decl, init)
  353.      tree decl, init;
  354. {
  355.   return 0;
  356.  
  357.   if (IS_AGGR_TYPE (TREE_TYPE (decl))
  358.       || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
  359.     init = extract_aggr_init (decl, init);
  360.   else
  361.     init = extract_scalar_init (decl, init);
  362.  
  363.   if (init == NULL_TREE)
  364.     return 0;
  365.  
  366.   DECL_INITIAL (decl) = init;
  367.   return 1;
  368. }
  369.